package com.ziytek.web.citizen.handler.client;

import io.netty.channel.*;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author fenghx
 * @version v1.0
 * @className BootNettyTcpChannelInitializer
 * @descripton 功能描述
 * @date 2023/4/13 10:24
 **/
@Slf4j
@ChannelHandler.Sharable
public class ClientTcpChannelInitializer<SocketChannel> extends ChannelInitializer<Channel> {

    public static long READ_TIME_OUT = 60;
    public static long WRITE_TIME_OUT = 60;
    public static long ALL_TIME_OUT = 60;

    @Override
    protected void initChannel(Channel ch) {

        ChannelPipeline pipeline = ch.pipeline();
        // 对 http 协议支持
        pipeline.addLast(new HttpServerCodec());
        // 聚合解码 httpRequest/httpContent/lastHttpContent到fullHttpRequest 保证接受的 http 请求完整
        pipeline.addLast(new HttpObjectAggregator(10 * 1024 * 1024));
        pipeline.addLast(new IdleStateHandler(READ_TIME_OUT, WRITE_TIME_OUT, ALL_TIME_OUT, TimeUnit.SECONDS));

        pipeline.addLast(new WebSocketServerProtocolHandler(
                "/ws",
                null,
                true,
                10 * 1024 * 1024
        ));

        pipeline.addLast(new ChannelDuplexHandler() {
            @Override
            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                if (cause instanceof IOException) {
                    // 处理 I/O 异常（如记录日志、关闭连接）
                    log.info("I/O Exception: {}", cause.getMessage());
                    ctx.close();
                } else {
                    // 其他异常处理
                    log.info("Internal Error: {}", cause.getMessage());
                    ctx.writeAndFlush("Internal Error: " + cause.getMessage());
                }
            }
        });

        pipeline.addLast(new WsWebSocketHandler());
    }
}